import re
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
from rest_framework import serializers
from django.conf import settings
from rest_framework_jwt.settings import api_settings
from .models import OAuthQQUser, OAuthSinaUser
from django_redis import get_redis_connection
from users.models import User

# class OAuthSinaUserSerializer(serializers.ModelSerializer):
#     """
#     Sina登录创建用户序列化器
#     """
#     access_token = serializers.CharField(label='操作凭证', write_only=True)
#     # mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
#     # password = serializers.CharField(label='密码', max_length=20, min_length=8)
#     # sms_code = serializers.CharField(label='短信验证码')
#     # username = serializers.CharField(min_length=1)
#     sms_code = serializers.CharField(max_length=6, min_length=6, write_only=True)
#     # access_token = serializers.CharField(write_only=True)
#     token = serializers.CharField(read_only=True)
#     user_id = serializers.IntegerField(read_only=True)
#     mobile = serializers.CharField(max_length=11)
#     class Meta:
#         model = User
#         fields = '__all__'
#         extra_kwargs = {
#             'username': {
#                 'read_only': True
#             },
#             'password': {
#                 'write_only': True
#             }
#         }
#
#     def validate_mobile(self, value):
#         if not re.match(r'^1[3-9]\d{9}$', value):
#             raise serializers.ValidationError('手机号格式不正确')
#
#         return value
#
#     def validate(self, attrs):
#
#         # 验证access_token
#         # 解密
#         tjs = TJS(settings.SECRET_KEY, 300)
#         try:
#             data = tjs.loads(attrs['access_token'])  #
#         except:
#             raise serializers.ValidationError('无效access_token')
#
#         access_token = data.get('access_token')
#         # attrs添加openid
#         attrs['access_token'] = access_token
#
#         # 验证短信验证码
#         # 1、获取reids中真实短信
#         conn = get_redis_connection('verify_codes')
#         rel_sms_code = conn.get('sms_%s'  % attrs['mobile'])
#         # 2、判断短信是否超过有效期
#         if not rel_sms_code:
#             raise serializers.ValidationError('短信验证码失效')
#         # 3、比对用户输入的短信和redis中真实短信
#         if attrs['sms_code'] != rel_sms_code.decode():
#             raise serializers.ValidationError('短信验证不一致')
#
#         # 判断手机号用户是否注册过
#         try:
#             user = User.objects.get(mobile=attrs['mobile'])
#         except:
#             # 未注册过，注册为新用户
#             return attrs
#         else:
#             # 注册过 查询用户进行绑定
#             # 判断密码
#             if not user.check_password(attrs['password']):
#                 raise serializers.ValidationError('密码错误')
#             attrs['user'] = user
#             attrs['access_token']=access_token
#             return attrs
#
#     def create(self, validated_data):
#
#         # 判断用户
#         user = validated_data.get('user', None)
#         if user is None:
#             # 创建用户
#             user = User.objects.create_user(username=validated_data['mobile'], password=validated_data['password'],
#                                             mobile=validated_data['mobile'])
#
#         # 绑定操作
#         OAuthSinaUser.objects.create(user=user, access_token=validated_data['access_token'])
#         # user_id=user.id
#         # 生成加密后的token数据
#         jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
#         jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
#
#         payload = jwt_payload_handler(user)  # 生成载荷部分
#         token = jwt_encode_handler(payload)  # 生成token
#
#         # user添加token属性
#         user.token = token
#         user.user_id = user.id
#
#         return user

# class OAuthQQUserSerializer(serializers.Serializer):
#     """
#     QQ登录创建用户序列化器
#     """
#     access_token = serializers.CharField(label='操作凭证')
#     mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
#     password = serializers.CharField(label='密码', max_length=20, min_length=8)
#     sms_code = serializers.CharField(label='短信验证码')
#
#     def validate(self, data):
#         # 检验access_token
#         access_token = data['access_token']
#         openid = OAuthQQUser.check_save_user_token(access_token)
#         if not openid:
#             raise serializers.ValidationError('无效的access_token')
#
#         # 将openid保存到校验好的数据中，方便其他方式使用，
#         data['openid'] = openid
#
#         # 检验短信验证码
#         mobile = data['mobile']
#         sms_code = data['sms_code']
#         redis_conn = get_redis_connection('verify_codes')
#         real_sms_code = redis_conn.get('sms_%s' % mobile)
#         if real_sms_code.decode() != sms_code:
#             raise serializers.ValidationError('短信验证码错误')
#
#         # 如果用户存在，检查用户密码
#         try:
#             user = User.objects.get(mobile=mobile)
#         except User.DoesNotExist:
#             pass
#         else:
#             password = data['password']
#             if not user.check_password(password):
#                 raise serializers.ValidationError('密码错误')
#             data['user'] = user
#         return data
#
#     def create(self, validated_data):
#
#         user = validated_data.get('user')
#         if not user:
#             # 用户不存在
#             user = User.objects.create_user(
#                 username=validated_data['mobile'],
#                 password=validated_data['password'],
#                 mobile=validated_data['mobile'],
#             )
#         #  保存用户user与qq openid的对应关系
#         OAuthQQUser.objects.create(
#             openid=validated_data['openid'],
#             user=user
#         )
#         return user

# 新浪序列化器
class OauthsinaSerializers(serializers.ModelSerializer):
    '''
        获取前端传递的参数mobile，password，sms_code，image_code,access_token
        从前端获取的数据，不返回到前端的话指定write_only，只进行反序列化
        如果要存储在数据库中，但是没有对应字段的话，需要添加属性
        从后端取出的数据，返回前端的话指定read_only，只进行序列化


        write_only:前端传递的数据，只判断不再返回前端
        read_only:后端查询生产的数据，只传递到前端，不保存到数据库



        '''
    # 显示指明模型类中没有的字段
    sms_code = serializers.CharField(max_length=6, min_length=6, write_only=True)
    # image_code = serializers.CharField(max_length=4, min_length=4, write_only=True)
    access_token = serializers.CharField(write_only=True)
    token = serializers.CharField(read_only=True)
    user_id = serializers.IntegerField(read_only=True)
    mobile = serializers.CharField(max_length=11)

    class Meta:
        model = User
        fields = ('mobile', 'password', 'sms_code', 'access_token',
                  'user_id', 'username', 'token')
        extra_kwargs = {
            'username': {
                'read_only': True
            },
            'mobile': {
                'write_only': True
            },
            'password': {
                'write_only': True
            }
        }

    # 验证手机号
    def validate_mobile(self, value):
        if not re.match(r'^1[3-9]\d{9}', value):
            raise serializers.ValidationError('手机号格式不正确')
        return value

    # 验证access_token和sms_code,image_code
    def validate(self, attrs):
        tjs = TJS(settings.SECRET_KEY, 3600)
        try:
            data = tjs.loads(attrs['access_token'])  # 字典形式
        except:
            raise serializers.ValidationError('access_token解密不正确')

        # 校验验证码
        conn = get_redis_connection('sms_code')
        code = conn.get('sms_code%s' % attrs['mobile'])
        if not code:
            raise serializers.ValidationError('短信验证码过期')
        if attrs['sms_code'] != code.decode():
            raise serializers.ValidationError('验证码不相等')
        # image_code = conn.get('Image_code_%s' % attrs['image_code_id'])
        # if not image_code:
        #     raise serializers.ValidationError('图片验证码过期')
        # if attrs['image_code_id'] != image_code.decode():
        #     raise serializers.ValidationError('验证码不相等')

        # 判断手机号用户是否注册过
        try:
            user = User.objects.get(mobile=attrs['mobile'])
            print(user.password)
        except:
            # 如果未注册，新建用户
            return attrs
        else:
            # 如果注册过，把用户和openid绑定,判断密码
            if not user.check_password(attrs['password']):
                raise serializers.ValidationError('密码不相等')
            attrs['user'] = user
        return attrs

    def create(self, validated_data):
        '''
        validated_data接收的是attrs，attrs里面没有绑定操作的数据
        attrs是前端传递过来的数据,里面没有user和userid，需要自定义属性
        1/保存到OAuthsinaUser和User表中
        :param validated_data:
        :return:
        '''
        # 判断用户
        user = validated_data.get('user', None)
        # del validated_data['access_token']

        if user is None:
            # del validated_data['access_token']
            # del validated_data['sms_code']
            validated_data['username'] = validated_data['mobile']
            user = User.objects.create_user(
                username=validated_data['username'],
                mobile = validated_data['mobile'],
                password=validated_data['password']
            )
        OAuthSinaUser.objects.create(
            user=user,
            openid=validated_data['access_token']
        )
        # 生产加密后的token数据
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)  # 生成载荷
        token = jwt_encode_handler(payload)  # 生成token

        # 对象添加属性
        user.token = token
        user.user_id = user.id
        user.save()
        return user